<?php 
namespace app\lib;

class BceSignService {
    private $ak;
    private $sk;

    public function __construct() {
        $this->ak = config('config.baiduyun.ak'); // 从配置文件读取
        $this->sk = config('config.baiduyun.sk');
    }

    /**
     * 生成Authorization头
     */
    public function generateAuthHeader($method, $uri, $params = [], $headers = [], $timestamp = '') {
        $headers['x-bce-date'] = $timestamp;
        $expiration = 1800;

        // 生成认证字符串前缀
        $authStringPrefix = "bce-auth-v1/{$this->ak}/{$timestamp}/{$expiration}";

        // 构建规范化请求（包含POST的body哈希）
        $canonicalRequest = $this->buildCanonicalRequest(
            strtoupper($method),
            $uri,
            $params,
            $headers
        );
        // 计算签名
        $signingKey = hash_hmac('sha256', $authStringPrefix, $this->sk);
        $signature = hash_hmac('sha256', $canonicalRequest, $signingKey);

        $signedHeaders = implode(';',array_keys($headers));

        return "{$authStringPrefix}/{$signedHeaders}/{$signature}";
    }

    private function buildCanonicalRequest($method, $uri, $params, $headers) {
        // URI编码（保留斜杠）
        $canonicalURI = $this->uriEncodeExceptSlash($uri);

        // 查询参数排序编码（处理重复键）
        ksort($params);
        $queryParts = [];
        foreach ($params as $key => $value) {
            $queryParts[] = rawurlencode($key) . '=' . rawurlencode($value);
        }
        $canonicalQuery = implode('&', $queryParts);

        // 头域处理（必须包含host和x-bce-date）
        $canonicalHeaders = 'host:' . ($headers['host'] ?? 'bcd.baidubce.com') . "\n"
                          . 'x-bce-date:' . urlencode($headers['x-bce-date']);

        // 拼接规范化请求
        // return "{$method}\n{$canonicalURI}\n{$canonicalQuery}\n{$canonicalHeaders}\n{$hashedBody}";
        return "{$method}\n{$canonicalURI}\n{$canonicalQuery}\n{$canonicalHeaders}";
    }

    /**
     * URI特殊编码（保留斜杠）
     */
    private function uriEncodeExceptSlash($path) {
        $path = $path === '' ? '/' : $path; // 空路径处理
        return str_replace('%2F', '/', rawurlencode($path));
    }
}

 ?>